package net.liteheaven.xblib.widget.scrollview;

import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.OverScroller;
import android.widget.ScrollView;

import net.liteheaven.xblib.common.java.ReflectUtil;

/**
 * 奥利奥滚动视图
 *
 * 特性：
 * 1.滚动位置位于顶部时，将触摸事件分发到下层
 * 2.顶部磁力区域
 *
 * Created by liangy on 2016/12/26.
 */
public class OreoScrollView extends ScrollView{

    private boolean mFlowJudge = false;
    private boolean mIsBeingDragged = false;
    private int mTouchSlop;
    private float mLastMotionY = 0f;
    private float mMagnetArea = 0;
    private boolean mScrollFinished = false;
    private int mFlingFlag = 0;

    public OreoScrollView(Context context) {
        super(context);
        init();
    }

    public OreoScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public OreoScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init(){
        ViewConfiguration config = ViewConfiguration.get(getContext());
        mTouchSlop = config.getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        int action = event.getAction();
        boolean intercept = false;
        switch (action) {
            case MotionEvent.ACTION_MOVE: {
                final float y = event.getY();
                float yDiff = y - mLastMotionY;
                float absYDiff = Math.abs(yDiff);

                if (!mFlowJudge) {
                    log("not judged yet");
                    if (absYDiff > mTouchSlop) {
                        log("diff large enough");
                        if (yDiff > 0) {
                            log("pull down");
                            mIsBeingDragged = (getScrollY() != 0);
                        } else {
                            log("pull up");
                            mIsBeingDragged = true;
                        }
                        mFlowJudge = true;
                        mLastMotionY = y;
                        intercept = mIsBeingDragged;
                    } else {
                        log("diff not large enough");
                        intercept = false;
                    }
                } else {
                    log("already judged " + mIsBeingDragged);
                    intercept = mIsBeingDragged;
                }
            }
            break;
            case MotionEvent.ACTION_DOWN: {
                log("ACTION_DOWN");
                mLastMotionY = event.getY();
                mFlowJudge = false;
                mIsBeingDragged = false;
                intercept = false;
            }
            break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL: {
                log("ACTION_UP");
                intercept = false;
            }
            break;
        }
        super.onInterceptTouchEvent(event);
        return intercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        // 检测fling
        mGestureDetector.onTouchEvent(ev);

        boolean result = super.onTouchEvent(ev);
        switch (ev.getAction()){
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                handleMagnetScroll();
                mFlingFlag = 0;
                break;
            case MotionEvent.ACTION_MOVE:
                break;
        }
        return result;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        sendOreoScrollBroadcast();
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        try{
            OverScroller scroller = (OverScroller) ReflectUtil.getFieldValue(this, "mScroller");
            if (!mScrollFinished && scroller.isFinished()){
                onScrollStop();
            }
            mScrollFinished = scroller.isFinished();

            //sendOreoScrollBroadcast();
        }catch (Exception e){
        }
    }

    private void sendOreoScrollBroadcast(){
        int scrollY = getScrollY();
        if (scrollY >= 0 && scrollY <= mMagnetArea){
            Intent intent = new Intent();
            String broadcastName = getOreoScrollBroadcastName(getContext());
            intent.setAction(broadcastName);
            int rate = (int)((float)scrollY * 100f / mMagnetArea);
            intent.putExtra("rate", rate);
            getContext().sendBroadcast(intent);
        }
    }

    public static String getOreoScrollBroadcastName(Context ctx){
        return ctx.getPackageName() + ".oreo_scroll";
    }

    private void onScrollStop(){
        handleMagnetScroll();
    }

    private void log(String text){
        boolean test = false;
        if (test){
        }
    }

    public void setTopMagnetArea(float area){
        mMagnetArea = area;
    }

    private void handleMagnetScroll(){
        float y = getScrollY();
        if (mMagnetArea <= 0){
            return;
        }
        if (y > 0 && y < mMagnetArea / 2){
            if (mFlingFlag < 0){
                smoothScrollTo(0, (int)mMagnetArea);
            }else{
                smoothScrollTo(0, 0);
            }

        }else if (y >= mMagnetArea / 2 && y < mMagnetArea){
            if (mFlingFlag > 0){
                smoothScrollTo(0, 0);
            }else{
                smoothScrollTo(0, (int)mMagnetArea);
            }
        }
    }

    private GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.OnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }

        @Override
        public void onShowPress(MotionEvent e) {

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {

        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            mFlingFlag = velocityY > 0 ? 1 : -1;
            return false;
        }
    };

    // 处理移动事件
    private GestureDetector mGestureDetector = new GestureDetector(getContext(), mOnGestureListener);
}
